package com.hcloud.libupload.task

import android.util.Log
import com.hcloud.libupload.bean.CommonPutReq
import com.hcloud.libupload.bean.CompleteReq
import com.hcloud.libupload.bean.FastUploadReq
import com.hcloud.libupload.bean.PutReq
import com.hcloud.libupload.callback.ICreateTaskCallback
import com.hcloud.libupload.comom.TaskControl
import com.hcloud.libupload.comom.UploadLib
import com.hcloud.libupload.excetion.UploadError
import com.hcloud.libupload.http.ProgressBody
import com.hcloud.libupload.request.UploadRequest
import com.hcloud.libupload.utils.PanUtil
import com.hcloud.libupload.utils.runOnUi
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.ByteArrayInputStream
import java.io.File

class PutUploadTask(
        uploadRequest: UploadRequest,
        taskControl: TaskControl,
        iCreateTaskCallback: ICreateTaskCallback
) : UploadTask(uploadRequest, taskControl, iCreateTaskCallback) {


    override fun commonPut() {
        super.commonPut()

        if (!File(uploadRequest.filePath).exists()) {
            throw UploadError(UploadError.UPLOAD_ERROR_10000, "the file is not exit !!!")
        }

        if (file.length() == 0L) {
            throw UploadError(UploadError.UPLOAD_ERROR_10003, "the file size is zero error !!!")
        }

        if (uploadRequest.requestId.isBlank()) {
            uploadRequest.requestId = PanUtil.getRequestId(UploadLib.instance().uploadConfig.phone)
        }

        runOnUi {
            iCreateTaskCallback.createSuccess(uploadRequest)
        }

        if (config.isFastUpload){
            fast()
        }else{
            putUpload()
        }
    }

    private fun fast() {
        var req = FastUploadReq(
                loginkey = UploadLib.instance().uploadConfig.loginKey,
                boxId = UploadLib.instance().uploadConfig.boxId,
                requestId = uploadRequest.requestId,
                filename = file.name,
                parentPath = uploadRequest.serverPath,
                filetype = fileType,
                size = file.length(),
                hash = fileHash,
                lastmod = file.lastModified().toString()
        )
        requestTask.fastUpload(req) {
            when (it.data.state) {
                0, 3 -> {
                    uploadSuccess()
                }
                1, 2 -> {
                    putUpload()
                }
                4 -> {
                    uploadRequest.requestId = PanUtil.getRequestId()
                    throw Exception()
                }
            }
        }
    }

    private fun putUpload() {

        val size = (file.length() / config.partSize).toInt()
        val offset = file.length() % config.partSize
        val allPart = if (offset == 0L) size else size + 1

        this.allPartSize = allPart
        Log.i("upload--sdk", "-----upload-----allPart-${allPartSize} ")

        if (uploadRequest.part == allPartSize) {
            if (!checkError()) {
                uploadSuccess()
            }
        } else {
            for (i in 0 until allPartSize) {

                if (i < uploadRequest.part) {
                    if (i == allPartSize - 1) {
                        if (offset == 0L) {
                            progress.currentSize += config.partSize
                        } else {
                            progress.currentSize += offset
                        }
                    } else {
                        progress.currentSize += config.partSize
                    }
                    continue
                }
                val partSize =
                        if (i == allPartSize - 1) {
                            if (offset == 0L) {
                                config.partSize.toString()
                            } else {
                                offset.toString()
                            }
                        } else {
                            config.partSize.toString()
                        }

                upload(i, partSize)
            }

            if (!checkError()) {
                uploadSuccess()
            }
        }
    }


    fun upload(index: Int, partSize: String) {
        try {

            if (uploadRequest.isCancel || uploadError != null) {
                return
            }

            var start = index.toLong() * config.partSize
            val partArray = file2Body.file2Body(file, start, partSize.toInt())
            val requestBody = partArray.toRequestBody("application/octet-stream".toMediaTypeOrNull())
            val progressBody = ProgressBody(
                    uploadRequest,
                    requestBody,
                    progress,
                    ByteArrayInputStream(partArray)
            )

            var name = PanUtil.getUrlEncoder(file.name)
            var serverPath = PanUtil.getUrlEncoder(uploadRequest.serverPath)
            val commonPutReq = CommonPutReq(
                    uploadId = uploadRequest.requestId,
                    authorization = UploadLib.instance().uploadAuth,
                    name = name,
                    path = serverPath,
                    fileType = fileType,
                    start = start.toString(),
                    length = partSize,
                    totalSize = file.length().toString(),
                    hash = fileHash,
                    requestBody = progressBody,
                    url = serverPath + name,
                    lastmod = file.lastModified().toString(),
                    longitude =  lonLatBean.longitude,
                    latitude = lonLatBean.latitude
            )
            Log.i("upload--sdk", "-----upload--count-----${commonPutReq.uploadId} start: ${commonPutReq.start}  size: ${commonPutReq.length} part: $index")

            requestTask.commonPut(commonPutReq, progressBody) {
                uploadRequest.part = index + 1
                runOnUi {
                    iPartSuccessCallback?.partSuccess(uploadRequest, progress)
                }
            }
        } catch (t: Throwable) {
            if (uploadError == null) {
                Log.i("upload-sdk", "start task---------part error--${t.message}-----")
                uploadError = t
            }
        }
    }



    private fun uploadSuccess() {
        runOnUi {
            iProgressCallback?.success(uploadRequest)
        }
    }
}